package match;

import fingerprint.*;
import database.*;

import java.sql.*;
import java.util.*;

/**
 * Created by ASUS on 2016/11/18.
 */
public class SongMatcher {
    public HashMap<Integer,ArrayList<Integer>> map=new HashMap<Integer,ArrayList<Integer>>();
    public SearchSF search=new SearchSF();
    private static final int time_level = 5;
    private ArrayList<ShazamHash> hashes;
    public SongMatcher(ArrayList<ShazamHash> hashes) {
         this.hashes = hashes;
     }

    private void match() {
        Collections.sort(hashes, new Comparator<ShazamHash>() {
            @Override
            public int compare(ShazamHash o1, ShazamHash o2) {
                return o1.finger_id-o2.finger_id;
            }
        });
        int lastId = -1;
        int currentId = 0;
        for (ShazamHash hash:hashes)
        {
            currentId = hash.finger_id;
            if(currentId!=lastId) {
                try {
                    ResultSet result = search.Searchfinger(hash.finger_id);
                    while (result.next()) {
                        int difference = result.getInt("offset") - hash.offset;
                        int song_id = result.getInt("id");
                        if (!map.containsKey(song_id)) {
                            map.put(song_id, new ArrayList<Integer>());
                        }
                        map.get(song_id).add(difference);
                    }
                }
                catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            lastId = currentId;
        }
    }

    public  ArrayList<Score> selectTarget() {
        match();
        ArrayList<Score> ret = new ArrayList<>();

        // iterate each possible song
        for (Iterator<Map.Entry<Integer, ArrayList<Integer>>> eachSong = map.entrySet().iterator();
             eachSong.hasNext(); ) {
            Map.Entry<Integer, ArrayList<Integer>> entry = eachSong.next();
            Integer song_id = entry.getKey();
            ArrayList<Integer> song_time_diff = entry.getValue();

            // convert to a histogram
            Collections.sort(song_time_diff);
            for (int i = 0; i < song_time_diff.size(); ++i) {
                song_time_diff.set(i, song_time_diff.get(i) / time_level);
            }

            int max = 1, count = 1;

            // count how many times the "mode" appears.
            // mode: n. (statistics) The mode is the value that is repeated most often in a data set.
            for (int i = 0, j = 1; j < song_time_diff.size(); ++i, ++j) {
                // count the length of each sub-series with repeating elements.
                if (Objects.equals(song_time_diff.get(i), song_time_diff.get(j))) {
                    count++;
                }

                // if such sub-series terminates.
                else {
                    if (count > max) {
                        max = count;
                    }
                    count = 1;
                }
            }

            Score score = new Score();
            score.id = song_id;
            score.score = max;
            ret.add(score);
        }

        Collections.sort(ret, new Comparator<Score>() {
            @Override
            public int compare(Score o1, Score o2) {
                return o2.score - o1.score;
            }
        });

        return ret;
    }
}
